#ifndef _Buffer_H
#define _Buffer_H

#include <string.h>
#include <assert.h>

class EDataBuffer{
public:
	EDataBuffer(size_t StartSize = 1024, size_t StepSize = 1024) : _Items(0), _Count(0), _Size(0), _StepSize(StepSize){
		expandIfNecessary(StartSize);
	}

	~EDataBuffer(){
		if (_Items){
			delete[] _Items;
		}
	}
	template<class T>
	inline size_t push_value(T Value){
		expandIfNecessary(sizeof(T));
		memmove(_Items + _Count, &Value, sizeof(T));
		size_t Index = _Count;
		_Count += sizeof(T);
		return Index;
	}

	inline size_t push(const void* SrcBuf, size_t Size){
		expandIfNecessary(Size);
		memmove(_Items + _Count, SrcBuf, Size);
		size_t Index = _Count;
		_Count += Size;
		return Index;
	}

	inline size_t reserve(size_t Size){
		expandIfNecessary(Size);
		size_t Index = _Count;
		_Count += Size;
		return Index;
	}

	inline void set(size_t Index, const char* SrcBuf, size_t Size){
		assert(!(Index + Size >= _Count));
		memmove(_Items + Index, SrcBuf, Size);
	}

	inline size_t count(){
		return _Count;
	}

	inline const void* getBuffer(){
		return _Items;
	}

	inline void reset(){
		_Count = 0;
	}
private:
	inline void expandIfNecessary(size_t NewDataSize){
		size_t RequiredSize = _Count + NewDataSize;
		if (RequiredSize > _Size){
			expand(RequiredSize);
		}
	}
	void expand(size_t RequiredSize);
	unsigned char* _Items;
	size_t _Count, _Size, _StepSize;
};

#endif /* _Buffer_H */